import os
import requests
import random
import string
from concurrent.futures import ThreadPoolExecutor, as_completed
from urllib3.util.retry import Retry
from requests.adapters import HTTPAdapter

def generate_random_filename(extension='.jpg'):
    """生成随机文件名"""
    random_str = ''.join(random.choices(string.ascii_lowercase + string.digits, k=8))
    return random_str + extension

def download_image(img_url, save_folder):
    """下载单张图片（带重试机制）"""
    try:
        # 设置重试机制（最多 3 次，超时 10 秒）
        session = requests.Session()
        retries = Retry(total=3, backoff_factor=1, status_forcelist=[500, 502, 503, 504])
        session.mount('https://', HTTPAdapter(max_retries=retries))
        session.mount('http://', HTTPAdapter(max_retries=retries))

        # 发送 GET 请求
        img_response = session.get(img_url, stream=True, timeout=10)
        if img_response.status_code == 200:
            # 生成随机文件名
            filename = generate_random_filename()
            filepath = os.path.join(save_folder, filename)

            # 保存图片（分块写入，减少内存占用）
            with open(filepath, 'wb') as f:
                for chunk in img_response.iter_content(1024):
                    f.write(chunk)
            print(f"已下载: {filepath}")
            return True
        else:
            print(f"下载失败: {img_url}, 状态码: {img_response.status_code}")
            return False
    except Exception as e:
        print(f"下载出错: {img_url}, 错误: {str(e)}")
        return False

def download_images_from_api(api_url, headers, data, save_folder):
    """从API获取图片URL并下载图片（多线程优化）"""
    # 创建保存文件夹（如果不存在）
    if not os.path.exists(save_folder):
        os.makedirs(save_folder)

    # 发送POST请求获取数据
    try:
        # 设置重试机制（最多 3 次，超时 10 秒）
        session = requests.Session()
        retries = Retry(total=3, backoff_factor=1, status_forcelist=[500, 502, 503, 504])
        session.mount('https://', HTTPAdapter(max_retries=retries))
        session.mount('http://', HTTPAdapter(max_retries=retries))

        # 发送 POST 请求（禁用 SSL 验证，仅用于测试）
        response = session.post(api_url, headers=headers, json=data, verify=False, timeout=10)
        response_data = response.json()

        # 检查请求是否成功
        if response_data.get('state') != 200:
            print(f"请求失败: {response_data.get('msg')}")
            return

        # 获取图片列表
        items = response_data.get('res', {}).get('item', [])
        if not items:
            print("没有找到图片")
            return

        # 使用线程池并行下载图片（最多 10 个线程）
        with ThreadPoolExecutor(max_workers=10) as executor:
            futures = []
            for item in items:
                img_url = item.get('img')
                if img_url:
                    futures.append(executor.submit(download_image, img_url, save_folder))

            # 等待所有任务完成
            for future in as_completed(futures):
                future.result()  # 如果某个任务失败，这里会抛出异常（但已经被捕获）

    except Exception as e:
        print(f"API 请求出错: {str(e)}")

if __name__ == "__main__":
    # API配置
    api_url = 'https://app.suzuk.cn/api/index/page'
    headers = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 MicroMessenger/6.8.0(0x16080000) NetType/WIFI MiniProgramEnv/Mac MacWechat/WMPF MacWechat/3.8.10(0x13080a10) XWEB/1227',
        'Content-Type': 'application/json',
        'xweb_xhr': '1',
    }  # 移除不必要的请求头

    # 保存文件夹
    save_folder = 'downloaded_images'

    # 多线程下载多个页面的图片
    with ThreadPoolExecutor(max_workers=5) as executor:  # 最多 5 个页面同时下载
        futures = []
        for i in range(1, 100):
            data = {
                'category': '5',
                'page': i
            }
            futures.append(executor.submit(download_images_from_api, api_url, headers, data, save_folder))

        # 等待所有任务完成
        for future in as_completed(futures):
            future.result()  # 如果某个任务失败，这里会抛出异常（但已经被捕获）